package com.bootdo.staticmask.common;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

/**
 * 执行linux命令工具包
 * Created by lkg on 17/8/16
 */
@Component
public class ExecuteCMD {
    private static Logger logger = LoggerFactory.getLogger(ExecuteCMD.class);
    // 保存进程的输入流信息
    private List<String> stdoutList = new ArrayList<>();
    // 保存进程的错误流信息
    private List<String> erroroutList = new ArrayList<>();

    /**
     * 执行linux 命令，并返回执行结果
     * @param cmd cmd命令
     * @return 执行结果
     */
    public String executeResult(String cmd) {
        try {
            Process ps = Runtime.getRuntime().exec(cmd);
            BufferedReader br = new BufferedReader(new InputStreamReader(ps.getInputStream()));
            StringBuffer sb = new StringBuffer();
            String line;
            while ((line = br.readLine()) != null) {
                sb.append(line).append("\n");
            }
            return sb.toString();
        } catch (Exception e) {
            logger.error("Execute cmd:" + cmd + "failed\n" + e);
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 执行linux 命令，并返回每行数据
     * @param cmd linux命令
     */
    public void executeLine(String cmd) {
        Process ps = null;
        try {
            logger.info("Execute cmd:" + cmd);
            ps = Runtime.getRuntime().exec(cmd);
            BufferedReader br = new BufferedReader(new InputStreamReader(ps.getInputStream()));
            StringBuffer sb = new StringBuffer();
            while (br.readLine() != null) {
                logger.info(br.readLine());
            }
        } catch (IOException e) {
            logger.error("Execute cmd:" + cmd + " failed\n" + e);
        }
    }

    /**
     * 执行linux的cmd命令，保持等待状态，修复bug
     * @param command linux命令
     */
    public int execute(String command) {
        // 先清空
        stdoutList.clear();
        erroroutList.clear();
        int exitValue = 1;
        Process p;
        try {
            logger.info(command);
            p = Runtime.getRuntime().exec(command);
            // 创建2个线程，分别读取输入流缓冲区和错误流缓冲区
            ThreadUtil stdoutUtil = new ThreadUtil(p.getInputStream(), stdoutList);
            ThreadUtil erroroutUtil = new ThreadUtil(p.getErrorStream(), erroroutList);
            //启动线程读取缓冲区数据
            stdoutUtil.start();
            erroroutUtil.start();

            exitValue = p.waitFor();//waitFor()等待操作完成,正常结束，Process的waitFor()方法返回0
        } catch (IOException e) {
            logger.error("Execute cmd:" + command + "failed. " + "because of IOException \n" + e);
        } catch (InterruptedException e) {
            logger.error("Execute cmd:" + command + "failed. " + "because of InterruptedException \n" + e);
        }
        return exitValue;
    }

    public List<String> getStdoutList() {
        return stdoutList;
    }

    public List<String> getErroroutList() {
        return erroroutList;
    }
}

class ThreadUtil implements Runnable {
    // 设置读取的字符编码
    private String character = "UTF-8";
    private List<String> list;
    private InputStream inputStream;

    public ThreadUtil(InputStream inputStream, List<String> list) {
        this.inputStream = inputStream;
        this.list = list;
    }

    public void start() {
        Thread thread = new Thread(this);
        thread.setDaemon(true);//将其设置为守护线程
        thread.start();
    }

    public void run() {
        BufferedReader br = null;
        try {
            br = new BufferedReader(new InputStreamReader(inputStream, character));
            String line = null;
            while ((line = br.readLine()) != null) {
                if (line != null) {
                    if (line.length() > 100) {
                        list.clear();
                    } else {
                        list.add(line);
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                //释放资源
                inputStream.close();
                br.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
